package ru.kradef.eclipse.plugin;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FormAttachment;
import org.eclipse.swt.layout.FormData;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
/**
 * 
 * The configuration UI tab. 
 * Encapsulates the user controls and interaction.
 *
 * @author D. Kranchev, kradef@gmail.com
 * @since 04.06.2012
 */
public class MainCompositeLaunchConfigurationTab extends
	AbstractLaunchConfigurationTab {

    public static final String SELECTED_CONFIGURATION_LIST = "selectedConfigurationList";
    private Combo availableConfigsCombo;
    private org.eclipse.swt.widgets.List selectedConfigsList;
    private Button delete;
    private Button add;
    private Set<String> allConfigNames;

    @Override
    public void createControl(Composite parent) {
	Composite controls = new Composite(parent, SWT.FILL);
	controls.setLayout(new FormLayout());

	Label label = new Label(controls, SWT.LEFT);
	label.setText("Available launch configurations: ");
	FormData f = new FormData();
	f.left = new FormAttachment(0, 5);
	f.top = new FormAttachment(0, 5);
	label.setLayoutData(f);

	availableConfigsCombo = new Combo(controls, SWT.LEFT | SWT.READ_ONLY);
	f = new FormData();
	f.left = new FormAttachment(label, 5);
	f.right = new FormAttachment(100, -100);
	f.top = new FormAttachment(0, 5);
	availableConfigsCombo.setLayoutData(f);

	add = new Button(controls, SWT.PUSH);
	add.setText("Add");
	add.setEnabled(false);
	f = new FormData();
	f.left = new FormAttachment(availableConfigsCombo, 5);
	f.right = new FormAttachment(100, -5);
	f.top = new FormAttachment(0, 4);
	add.setLayoutData(f);

	Label selectiosLabel = new Label(controls, SWT.LEFT);
	f = new FormData();
	f.left = new FormAttachment(0, 5);
	f.top = new FormAttachment(availableConfigsCombo, 5);
	selectiosLabel.setLayoutData(f);

	selectiosLabel.setText("Selected launch configurations:");
	selectedConfigsList = new org.eclipse.swt.widgets.List(controls,
		SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL
			| SWT.MULTI);
	f = new FormData();
	f.left = new FormAttachment(label, 5);
	f.right = new FormAttachment(100, -5);
	f.top = new FormAttachment(availableConfigsCombo, 5);
	f.bottom = new FormAttachment(100, -35);
	selectedConfigsList.setLayoutData(f);

	delete = new Button(controls, SWT.PUSH);
	delete.setText("Remove");
	f = new FormData();
	f.left = new FormAttachment(100, -100);
	f.right = new FormAttachment(100, -5);
	f.top = new FormAttachment(selectedConfigsList, 5);
	delete.setLayoutData(f);
	delete.setEnabled(false);
	
	addListenerrs();
	setControl(controls);
    }

    private void addListenerrs() {
	add.addListener(SWT.Selection, new Listener() {
	    @Override
	    public void handleEvent(Event event) {
		onAddClicked();
	    }
	});
	
	delete.addListener(SWT.Selection, new Listener() {
	    @Override
	    public void handleEvent(Event event) {
		onDeleteClicked();
	    }
	});

	Listener selectionListener = new Listener() {

	    @Override
	    public void handleEvent(Event event) {
		if (event.type == SWT.Selection) {
		    updateButtonsState();
		}
	    }
	};
	availableConfigsCombo.addListener(SWT.Selection, selectionListener);
	selectedConfigsList.addListener(SWT.Selection, selectionListener);
    }

    protected void updateButtonsState() {
	add.setEnabled(availableConfigsCombo.getSelectionIndex() >= 0);
	delete.setEnabled(selectedConfigsList.getSelectionCount() > 0);
    }

    protected void onDeleteClicked() {
	if (selectedConfigsList.getSelectionCount() == 0) {
	    return;
	}
	String[] selection = selectedConfigsList.getSelection();
	StringBuilder b = new StringBuilder();
	for (String item : selection) {
	    if (b.length() > 0) {
		b.append(", ");
	    }
	    b.append(item);
	}
	int response = ask("Are you shure you want to remove [" + b.toString()
		+ "]?", "Removing launch configuration");
	if (response != SWT.YES) {
	    return;
	}

	selectedConfigsList.remove(selectedConfigsList.getSelectionIndices());
	for (String item : selection) {
	    if (allConfigNames.contains((String) item)) {
		availableConfigsCombo.add(item);
	    }
	}
	updateButtonsState();
	updateLaunchConfigurationDialog();
    }

    private int ask(String message, String title) {
	Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
		.getShell();
	MessageBox messageBox = new MessageBox(shell, SWT.ICON_QUESTION
		| SWT.YES | SWT.NO);
	messageBox.setMessage(message);
	messageBox.setText(title);
	return messageBox.open();
    }

    private void onAddClicked() {
	int selectionIndex = availableConfigsCombo.getSelectionIndex();
	if (selectionIndex < 0) {
	    return;
	}
	String selectedItem = availableConfigsCombo.getItem(selectionIndex);
	int response = ask("It's about to add [" + selectedItem + "]?",
		"Add lauch configuration");
	if (response != SWT.YES) {
	    return;
	}
	selectedConfigsList.add(selectedItem);
	availableConfigsCombo.remove(selectionIndex);
	updateButtonsState();
	updateLaunchConfigurationDialog();
    }

    @Override
    public void setDefaults(ILaunchConfigurationWorkingCopy configuration) {
	// nothing to do
    }

    @Override
    public void initializeFrom(ILaunchConfiguration configuration) {
	ILaunchManager launchManager = getLaunchManager();
	ILaunchConfiguration[] launchConfigurations;
	try {
	    launchConfigurations = launchManager.getLaunchConfigurations();
	} catch (CoreException e) {
	    // todo: may be this is the case to throw exception?
	    setErrorMessage(e.getMessage());
	    return;
	}
	List selectedList = Collections.emptyList();
	try {
	    selectedList = configuration.getAttribute(
		    SELECTED_CONFIGURATION_LIST, Collections.emptyList());
	} catch (CoreException e) {
	    setErrorMessage(e.getMessage());
	}
	availableConfigsCombo.removeAll();
	allConfigNames = new HashSet<String>();
	for (ILaunchConfiguration conf : launchConfigurations) {
	    String configurationName = conf.getName();
	    if (!configurationName.equals(configuration.getName())
		    && !selectedList.contains(configurationName)) {
		availableConfigsCombo.add(configurationName);
	    }
	    allConfigNames.add(configurationName);
	}
	selectedConfigsList.removeAll();
	for (Object item : selectedList) {
	    selectedConfigsList.add((String) item);
	    if (!allConfigNames.contains((String) item)) {
		setErrorMessage("Configuration [" + item + "] is undefined");
	    }
	}
	updateButtonsState();
    }

    @Override
    public boolean isValid(ILaunchConfiguration launchConfig) {
	if (selectedConfigsList.getItemCount() == 0) {
	    setErrorMessage("At least one configuration should be selected");
	    return false;
	}
	for (String item : selectedConfigsList.getItems()) {
	    if (!allConfigNames.contains((String) item)) {
		setErrorMessage("Configuration [" + item + "] is undefined");
		return false;
	    }
	}
	setErrorMessage(null);
	return super.isValid(launchConfig);
    }

    @Override
    public void performApply(ILaunchConfigurationWorkingCopy configuration) {
	List<String> selectedList = new ArrayList<String>(
		selectedConfigsList.getItemCount());
	for (String item : selectedConfigsList.getItems()) {
	    selectedList.add(item);
	}
	configuration.setAttribute(SELECTED_CONFIGURATION_LIST, selectedList);
    }

    @Override
    public String getName() {
	return "Composite";
    }

}
